// // Copyright (c) 2009 All Right Reserved // // vl // // 2009-01-01 // Contains ... using System.Collections.Generic; using System.Diagnostics.Contracts; using System.IO; using System.Linq; using System.Xml; using System.Xml.Linq; using JetBrains.Annotations; using LargoCommon.Music; namespace LargoCommon.Support { /// /// Music Xml. /// public sealed class MusicXmlWriter { #region Constructors /// /// Initializes a new instance of the MusicXmlWriter class. /// /// The given file. public MusicXmlWriter(MusicalBundle givenFile) { Contract.Requires(givenFile != null); this.MusicalBundle = givenFile; this.MusicalBlock = givenFile.Blocks.FirstOrDefault(); var musicalBlock = this.MusicalBlock; if (musicalBlock != null) { this.MusicalTracks = (from mt in musicalBlock.Strip.Lines orderby mt.LineIndex select mt).ToList(); } } /// /// Initializes a new instance of the class. /// [UsedImplicitly] public MusicXmlWriter() { } #endregion #region Properties /// /// Gets Musical File. /// /// Property description. // ReSharper disable once UnusedAutoPropertyAccessor.Local private MusicalBundle MusicalBundle { get; } /// Gets Musical block. /// Property description. /// Returns value. private MusicalBlock MusicalBlock { get; } /// Gets file name. /// Property description. /// Returns value. private List MusicalTracks { get; } /// /// Gets or sets MusicXml Header. /// private MusicXmlHeader Header { get; set; } #endregion #region Public interface /// /// Write Music Xml. /// /// Stream writer. public void WriteTo(TextWriter streamWriter) { Contract.Requires(streamWriter != null); //// Document type //// ""; var decl = new XDeclaration("1.0", "utf-8", "no"); var comment = new XComment("Music Xml"); //// XProcessingInstruction pi = new XProcessingInstruction(); var doc = new XDocument(decl, comment); //// ""; var documentType = new XDocumentType("score-partwise", "-//Recordare//DTD MusicXml 3.0 Partwise//EN", "http://www.musicxml.org/dtds/partwise.dtd", null); doc.Add(documentType); //// Score Partwise - doc.Root element name ="score-partwise" var scorePartwise = new XElement( "score-partwise", new XAttribute("version", "3.0")); this.Header = new MusicXmlHeader(scorePartwise, this.MusicalBlock); this.Header.WriteXmlHeader(); var element = this.ScorePartListElement(); this.Header.ScorePartwise.Add(element); //// ????? XElement element = this.TempoElement(); scorePartwise.Add(element); foreach (var partElement in this.MusicalTracks.Select(this.PartElement)) { scorePartwise.Add(partElement); } doc.Add(scorePartwise); //// Saving var outputSettings = new XmlWriterSettings { NewLineOnAttributes = true, Indent = true }; using (var xmlWriter = XmlWriter.Create(streamWriter, outputSettings)) { doc.Save(xmlWriter); } } #endregion #region ScorePartList /// /// Score Part List element. /// /// Returns value. private XElement ScorePartListElement() { var partList = new XElement("part-list"); foreach (var track in this.MusicalBlock.Strip.Lines) { var instr = track.FirstStatus.Instrument?.MelodicInstrument ?? MidiMelodicInstrument.AcousticGrandPiano; if (track.FirstStatus.Instrument != null) { var number = track.FirstStatus.Instrument.Number; var scorePartObject = new ScorePartObject { Id = "P" + track.LineIndex, PartName = instr.ToString(), ScoreInstrumentId = "I" + number, MidiInstrumentId = "I" + number, InstrumentName = instr.ToString(), MidiProgram = number, MidiChannel = track.MainVoice.Channel }; var scorePart = scorePartObject.ScorePart(); partList.Add(scorePart); } } return partList; } #endregion #region Musical Parts /// /// Part element. /// /// Musical track. /// Returns value. private XElement PartElement(MusicalLine track) { Contract.Requires(this.MusicalBlock != null); Contract.Requires(track != null); var part = new XElement( "part", new XAttribute("id", "P" + track.LineIndex)); for (var barNumber = 1; barNumber <= this.MusicalBlock.Header.NumberOfBars; barNumber++) { //// MusicXmlMeasure musicXmlMeasure = new MusicXmlMeasure(this.Header); var measure = MusicXmlMeasure.MeasureElement(barNumber, track, this.MusicalBlock.Header); part.Add(measure); } return part; } #endregion } }